package com.gopay.bis.manager.bank.expay;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.TransUtils;
import com.gopay.bis.dao.bankorder.BankOrderDAO;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.trans.CurrencyCode;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.ipay.expay.AuthenBindCard;
import com.gopay.common.domain.bank.ipay.expay.BindCardPay;
import com.gopay.common.domain.bank.ipay.expay.Body;
import com.gopay.common.domain.bank.ipay.expay.Head;
import com.gopay.common.domain.bank.ipay.expay.IpayExPayBaseMessage;
import com.gopay.common.domain.bank.ipay.expay.Query;
import com.gopay.common.domain.bank.ipay.expay.Refund;
import com.gopay.common.domain.bank.ipay.expay.UnBindCard;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.businesses.ExPayService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 民生i支付快捷报文组装
 * 
 * @CmbcExPayManager.java
 * @author jiangxiangjiao
 */
public class IpayExPayManager {

	@Resource(name = "ipayExPayServiceClient")
	private ExPayService ipayExPayServiceClient;

	//@Resource(name = "ProductInfoDAO")
	//protected ProductInfoDAO ProductInfoDAO;
	@Resource(name = "iPayConfig")
	private Map<String, String> iPayConfig;
	
	@Resource(name = "bankOrderDAO")
	BankOrderDAO bankOrderDAO;
	
	/**
	 * 平台发送实名身份认证请求
	 * 
	 * @param message
	 * @return
	 * @throws GopayException
	 */
	public Object certification(IpayExPayBaseMessage message) throws GopayException {
		Head head = createHead();
		AuthenBindCard bindCardBody = new AuthenBindCard();
		bindCardBody.setReqMsgId("QY" + message.getOrderId()); // 报文请求流水号
		bindCardBody.setAccountName(message.getCardHolder());
		bindCardBody.setBankCardNo(message.getCardNo());
		if(BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)){
			bindCardBody.setBankCardType("02"); // 信用卡
		}
		if(BisBankBusinessProd._15.value.equals(message.getBankBusProd().value)){
			bindCardBody.setBankCardType("01"); // 借记卡
		}
		bindCardBody.setCertificateNo(message.getIdentityCode());
		bindCardBody.setCertificateType("ZR01"); // ZR01--身份证
		bindCardBody.setCvn2(message.getCvv2());
		bindCardBody.setMobilePhone(message.getMediaId());
		bindCardBody.setUserId(message.getIdentityCode()); // 商户用户标识--用户在合作方端注册时的唯一标识：如账户
		bindCardBody.setValid(message.getAvailableDate());

		IpayExPayBaseMessage req = new IpayExPayBaseMessage();
		BeanUtils.copyProperties(message, req);
		req.setTraceId(new DateTime().toString("YYYYMMddHHmmss") +bindCardBody.getReqMsgId()); // 报文跟踪码 = 时间戳+报文请求流水号
		req.setHead(head);
		req.setBody(bindCardBody);
		req.setPlainMessage(buildPlainMessage(req, AuthenBindCard.class));
		req.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerCertificationSendLog(req);
		IpayExPayBaseMessage resMsg = (IpayExPayBaseMessage) ipayExPayServiceClient.sign(req);
		resMsg.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerCertificationReturnLog(resMsg);
		return resMsg;
	}

	/**
	 * 平台发送解绑卡请求
	 * 
	 * @param message
	 * @param bindCardId 带解绑的绑卡ID
	 * @return
	 * @throws GopayException
	 */
	public Object UnBindCard(IpayExPayBaseMessage message,String bindCardId) throws GopayException {
		Head head = createHead();
		UnBindCard unBindCardBody = new UnBindCard();
		unBindCardBody.setBindId(bindCardId);
		unBindCardBody.setReqMsgId("JY"+ message.getOrderId()); //报文请求流水号
		unBindCardBody.setUserId(message.getIdentityCode()); 
		IpayExPayBaseMessage req = new IpayExPayBaseMessage();
		BeanUtils.copyProperties(message, req);
		req.setTraceId(new DateTime().toString("YYYYMMddHHmmss") +unBindCardBody.getReqMsgId()); // 报文跟踪码 = 时间戳+报文请求流水号
		req.setHead(head);
		req.setBody(unBindCardBody);
		req.setPlainMessage(buildPlainMessage(req, UnBindCard.class));
		req.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayUnBindCardSendLog(req);
		IpayExPayBaseMessage resMsg = (IpayExPayBaseMessage) ipayExPayServiceClient.cancel(req);
		resMsg.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayUnBindCardRetuenLog(resMsg);
		return resMsg;
	}

	/**
	 * 平台发送代扣请求
	 * 
	 * @param message
	 * @return
	 * @throws GopayException
	 */
	public Object payment(IpayExPayBaseMessage message,String bindCardId) throws GopayException {
		Head head = createHead();
		BindCardPay payBody = new BindCardPay();
		payBody.setReqMsgId(message.getBankOrderId()); // 报文请求流水号--国付宝订单号
		payBody.setUserId(message.getIdentityCode()); 
		payBody.setBindId(bindCardId); // 绑卡ID
		payBody.setCurrency(CurrencyCode.CNY.value);
		payBody.setAmount(TransUtils.amountConvert2Fen(message.getAmount().toString()));
		payBody.setProductCategory(iPayConfig.get("IPAY.EXPAY.PRODUCTCATEGORY")); // 01 --虚拟产品（测试环境为01，生产为05）
		//PgGenOrderTransDtl dtl = ProductInfoDAO.findProductInfoByGopayOrderId(message.getOrderId());
		payBody.setProductName(message.getOrderId()); // 商品名称
		//payBody.setProductDesc(dtl.getGoodsInfo()); // 商品描述

		IpayExPayBaseMessage req = new IpayExPayBaseMessage();
		BeanUtils.copyProperties(message, req);
		req.setTraceId(message.getOrderId()); // 支付--以国付宝银行订单号作为报文跟踪码
		req.setHead(head);
		req.setBody(payBody);
		req.setPlainMessage(buildPlainMessage(req, BindCardPay.class));
		req.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerPaymentSendLog(req);
		IpayExPayBaseMessage resMsg = (IpayExPayBaseMessage) ipayExPayServiceClient.payment(req);
		resMsg.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerPaymentReturnLog(resMsg);
		return resMsg;
	}
	
	public Object refund(IpayExPayBaseMessage message) throws GopayException {
		Head head = createHead();
    	Refund refund = new Refund();
    	refund.setReqMsgId(message.getBankOrderId());
    	refund.setCurrency(CurrencyCode.CNY.value);
    	refund.setAmount(TransUtils.amountConvert2Fen(message.getAmount().toString()));
    	refund.setRefundReason((StringUtils.isEmpty(message.getTermination()) ? "退款" : message.getTermination()));
    	refund.setOriPayMsgId(message.getBankReturnOrderId());
    	IpayExPayBaseMessage req = new IpayExPayBaseMessage();
    	BeanUtils.copyProperties(message, req);
    	req.setHead(head);
    	req.setBody(refund);
    	
    	req.setTraceId(getShortUuid());
    	req.setPlainMessage(buildPlainMessage(req, Refund.class));
    	BankLogUtils.printExpayManagerRefundSendLog(req);
		IpayExPayBaseMessage resMsg = (IpayExPayBaseMessage) ipayExPayServiceClient.refund(req);
		BankLogUtils.printExpayManagerRefundReturnLog(resMsg);
		return resMsg;
	}

	/**
	 * 平台发送代扣查询请求
	 * 
	 * @param message
	 * @return
	 * @throws GopayException
	 */
	public Object query(IpayExPayBaseMessage message) throws GopayException {
		Head head = createHead();
		Query queryBody = new Query();
		queryBody.setOriReqMsgId(message.getBankOrderId()); // 原请求交易流水号

		IpayExPayBaseMessage req = new IpayExPayBaseMessage();
		BeanUtils.copyProperties(message, req);
		req.setTraceId("CX" + message.getOrderId()); // 报文跟踪码
		req.setHead(head);
		req.setBody(queryBody);
		req.setPlainMessage(buildPlainMessage(req, Query.class));
		req.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerQuerySendLog(req);
		IpayExPayBaseMessage resMsg = (IpayExPayBaseMessage) ipayExPayServiceClient.queryOrder(req);
		Query queryRes = (Query) resMsg.getBody();
		queryRes.setOriAmount(TransUtils.amountConvert2Yuan((StringUtils.isEmpty(queryRes.getOriAmount()))? "0" :queryRes.getOriAmount()));
		resMsg.setOutStlmCd(BankConstants.BANK_LOGO_IPAY);
		BankLogUtils.printExPayManagerQueryReturnLog(resMsg);
		return resMsg;
	}
	
	/**
	 * 平台发送绑卡记录查询请求
	 * 
	 * @param message
	 * @return
	 * @throws GopayException
	 */
	public Object signQuery(IpayExPayBaseMessage message) throws GopayException {
		return null;
	}
	
	public Head createHead() {
		Head head = new Head();
		head.setMsgType("01");
		head.setVersion("1.0.0");
		head.setReqDate(new DateTime().toString("yyyyMMddHHmmss"));
		return head;
	}

	public <T> String buildPlainMessage(Object msg, Class<T> bodyCla) {
		XStream xstream = new XStream(new DomDriver("UTF-8", new NoNameCoder()));
		xstream.processAnnotations(msg.getClass());
		xstream.addDefaultImplementation(bodyCla, Body.class);
		xstream.alias("message", msg.getClass());
		return xstream.toXML(msg);
	}

	public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
			"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8",
			"9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
			"U", "V", "W", "X", "Y", "Z" };

	public static String getShortUuid() {
		StringBuffer stringBuffer = new StringBuffer();
		String uuid = UUID.randomUUID().toString().replace("-", "");
		for (int i = 0; i < 8; i++) {
			String str = uuid.substring(i * 4, i * 4 + 4);
			int strInteger = Integer.parseInt(str, 16);
			stringBuffer.append(chars[strInteger % 0x3E]);
		}
		return stringBuffer.toString().toLowerCase();
	}

}
